home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Pascal Super Library
/
Pascal Super Library (CW International)(1997).bin
/
TSR
/
TPPOP18C
/
UNHOOK.PAS
< prev
next >
Wrap
Pascal/Delphi Source File
|
1988-11-08
|
5KB
|
176 lines
{$A+,B-,D+,E-,F-,I+,L+,N-,O-,R-,S-,V-}
Unit Unhook;
{ Copyright (c)1988 Ross Neilson Wentworth }
{ Serendipity Software }
{ 1422 Elkgrove Circle, #3 }
{ Venice, CA 90291 }
{ All Rights Reserved }
{ This unit provides almost everything that is necessary to remove a }
{ resident program from memory. Examine the provided example NODICE }
{ to see how easy it is to use. }
Interface
Uses Dos;
Function Installed(MultId : Byte) : Boolean;
{ Returns true if the resident program with the matching I.D. is loaded. }
Function OkToRemove(MultID : Byte) : Boolean;
{ Returns true if it is safe to unload the resident }
{ program with the matching I.D. number. }
Procedure RemoveProgram(MultID : Byte);
{ Removes the program with the matching I.D. from memory. }
Implementation
Type
VectorTable = Record
Number : Byte;
OldInt : Pointer;
Offset : Word;
End;
VectorArray = Array[1..2] of VectorTable;
VectorPtr = ^VectorArray;
Function DosVersion : Word;
{ Returns the DOS version as a word. It swaps the two bytes }
{ to make tests more logical, i.e. DosVersion < $0300 }
InLine($B4/$30/ { mov ah,30h }
$CD/$21/ { int 21h }
$86/$E0); { xchg ah,al }
{==========================================================}
{ The following routines should only be called after it is }
{ verified that the program is active by calling INSTALLED }
{ Running these without the program being active could be }
{ dangerous! }
{==========================================================}
Function CheckSignature(MultId : Byte) : Byte;
{ Returns true a status byte indicating if the program is loaded }
InLine($58/ { pop ax }
$88/$C4/ { mov ah,al }
$B0/$00/ { mov al,0 }
$CD/$2F); { int 2Fh }
Function GetTable(MultId : Byte) : Pointer;
{ Returns a pointer to the vector table }
InLine($58/ { pop ax }
$88/$C4/ { mov ah,al }
$B0/$01/ { mov al,1 }
$CD/$2F); { int 2Fh }
Function GetCseg(MultId : Byte) : Word;
{ Returns the popup's code segment }
InLine($58/ { pop ax }
$88/$C4/ { mov ah,al }
$B0/$02/ { mov al,2 }
$CD/$2F); { int 2Fh }
Procedure ReleaseMemory(MultId : Byte);
{ Releases the popup's memory }
InLine($58/ { pop ax }
$88/$C4/ { mov ah,al }
$B0/$03/ { mov al,3 }
$CD/$2F); { int 2Fh }
Function GetEndOffset(MultId : Byte) : Word;
{ Returns the popup's code segment }
InLine($58/ { pop ax }
$88/$C4/ { mov ah,al }
$B0/$04/ { mov al,4 }
$CD/$2F); { int 2Fh }
{==========================================================}
Function Installed(MultID : Byte) : Boolean;
{ Returns TRUE if the program is active in memory }
Var
TempV : Pointer;
Begin
Installed := False;
If DosVersion < $0300 Then
Begin { DOS 2.x }
GetIntVec($2F,TempV);
If TempV = Nil Then Exit;
End;
If CheckSignature(MultId) = $FF Then Installed := True;
End;
Function OkToRemove(MultID : Byte) : Boolean;
{ Returns TRUE if it is safe to remove the program }
Var
OldVector : Pointer;
NewVector : Pointer;
Index : Integer;
PopCSeg : Word;
Table : VectorPtr;
EndOfs : Word;
Begin
OkToRemove := False;
EndOfs := GetEndOffset(MultId);
If EndOfs <> MemW[PrefixSeg:$002C] Then Exit;
PopCSeg := GetCSeg(MultId);
Table := GetTable(MultId);
Index := 1;
While Table^[Index].Number <> 0 Do
{ compares the current value of the interrupt vector with what the }
{ resident program set it to. If ALL of them are unchanged then it }
{ is safe to remove the program from memory. }
Begin
GetIntVec(Table^[Index].Number,NewVector);
OldVector := Ptr(PopCSeg,Table^[Index].Offset);
If OldVector <> NewVector Then Exit;
Inc(Index);
End;
OkToRemove := True;
End;
Procedure RemoveProgram(MultID : Byte);
{ Removes the program from memory }
Var
Index : Integer;
Table : VectorPtr;
Begin
ReleaseMemory(MultID); { release the memory }
Table := GetTable(MultId);
Index := 1;
While Table^[Index].Number <> 0 Do { restore the interrupt vectors }
Begin
SetIntVec(Table^[Index].Number,Table^[Index].OldInt);
Inc(Index);
End;
End;
End.